fix(api): clean dynamic API HTTP and connection errors#45
Open
arseniy-pplx wants to merge 1 commit into
Open
Conversation
Dynamic `tangle api <group> <op>` calls now fail with a concise, one-line, credential-safe message and a non-zero exit instead of a raw traceback or a truncated HTTP status exit code. - HTTP status errors report `HTTP <status> <reason> for <METHOD> <url>` with a whitespace-normalized, length-bounded slice of the backend body. - Connection, timeout, proxy, and TLS errors report an actionable reason. - URLs are sanitized: userinfo, credential query params, Authorization, and presigned/SAS-URL signatures are redacted. IPv6 literals are re-bracketed so host and port survive redaction (`[2001:db8::1]:8443`). - Free-form exception text is scrubbed for embedded URLs and `user:pass@host` userinfo before display, so a crafted or third-party proxy/connect error cannot leak credentials while errno/TLS diagnostics are preserved. - Exit codes are now a non-zero string exit (1) rather than the HTTP status, which was truncated to 8 bits (404 -> 148, 512 -> 0). - Schema refresh/fetch failures reuse the same formatting and keep omitting the response body so an auth failure cannot reflect sent credentials. The original exception is preserved as the cause for Python callers, and programmatic clients still receive raw httpx exceptions.
arseniy-pplx
marked this pull request as ready for review
July 20, 2026 18:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Dynamic
tangle api <group> <op>calls (and the OpenAPI schema refresh/fetch path) now fail with a concise, one-line, credential-safe message and a non-zero exit code instead of a raw traceback or a truncated HTTP status exit code.HTTP <status> <reason> for <METHOD> <url>with a whitespace-normalized, length-bounded slice of the backend body.connection failed: [Errno 111] Connection refused,read timed out,TLS error: ...).user:pass@userinfo and redacts credential query params,Authorization, and presigned/SAS-URL signatures (AWS SigV4 / GCS / Azure). IPv6 literals are re-bracketed so host and port survive redaction (https://<redacted>@[2001:db8::1]:8443/...).user:pass@hostuserinfo before display, so a crafted or third-party proxy/connect error string cannot leak credentials — while benign diagnostics (errno, TLS reason) are preserved./openapi.jsonresponse body, so an auth failure cannot reflect the credentials just sent.The original exception is preserved as the cause (
raise ... from exc) for Python callers; programmatic clients still receive rawhttpxexceptions. Changes are confined toapi_transport.pyandapi_cli.py; the existing actionable cache-missing behavior and API command exit semantics are unchanged.Context
Dynamic
tangle apicalls previously surfaced backend failures either as a raw traceback or as an HTTP status pushed through the process exit code, where the value was truncated to 8 bits (404 → 148, 512 → 0 false success). This renders every failure as one concise, credential-safe line with a correct non-zero exit code, without changing the success path or the actionable cache-missing behavior.Testing
uv run pytest tests/test_api_transport.py— URL sanitization (userinfo, credential/query params, presigned signatures, IPv6 re-bracketing with userinfo+port), one-line status errors, bounded/normalized detail, detail omission, actionable request-error classification, embedded-secret scrubbing for proxy/connect exception text, and benign errno/TLS diagnostics preserveduv run pytest tests/test_api_cli.py— passes except one pre-existing failure (test_official_static_command_without_schema_fails_with_actionable_error) that reproduces identically on the base commit and is unrelated to this changeuvx ruff checkon the touched filesuv lock --check;uv buildgit diff --checkFailed to reach GET http://<redacted>@127.0.0.1:1/api/pipeline_runs/: connection failed: [Errno 111] Connection refused, exit 1